using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Threading;
using BusinessFramework.AOP;
using NUnit.Framework;
using SpecUnit;

namespace BusinessFramework.Tests
{
    [TestFixture, Ignore]
    public class Misc
    {
        public class DynamicPropertyClass : EntityBase<DynamicPropertyClass>
        {
            public DynamicPropertyClass()
            {
                Extensions.AllowDynamicProperties();
            }
            [DynamicProperty]
            public string String { get; set; }

            [DynamicProperty]
            public int Int { get; set; }

            public string Simple { get; set; }
        }
        
        [Test]
        public void Abc()
        {
            var d = new DynamicPropertyClass();
            d.Extensions.AllowDynamicProperties();
            d.String = "abc";
            d.Int = 4;

            d.Extensions.DynamicProperties["String"].ShouldEqual("abc");
            d.Extensions.DynamicProperties["Int"].ShouldEqual(4);
        }

        public class Value
        {
            public string Key { get; set; }
        }
        
        private class PropertyAccess
        {
            public int Number { get; set; }
            public T GetProperty<T>(string name)
            {
                return (T) (object) Number;
            }

            public T GetPropertyReflection<T>(string name)
            {
                return (T)GetType().GetProperty(name).GetGetMethod().Invoke(this, new object[0]);
            }
        }

        [Test]
        public void DynamicPropertyAccess()
        {
            var e = new PropertyAccess();
            TestTime.Start(1e6, () => e.GetProperty<int>("Number"));
            TestTime.Start(1e6, () => e.GetPropertyReflection<int>("Number"));
        }

        [Test]
        public void Lambda()
        {
            var lambda = Expression.Lambda(
                Expression.Constant(5)
                );

            var d = lambda.Compile();
            TestTime.Start(1e6, () => d.DynamicInvoke());

            var lambda2 = Expression.Lambda<Func<int>>(
                Expression.Constant(5));

            var d2 = lambda2.Compile();
            TestTime.Start(1e8, () => d2());
        }

        [Test]
        public void GetTypeTest()
        {
            TestTime.Start(1e6, () => GetType());
        }

        
        [Test]
        public void Boxing()
        {
            TestTime.Start(1e8, () => {
                                    int box = 4;
                                    int b = (int) (object) box;
                                    int x  = 5*b;
                                });

            TestTime.Start(1e8, () =>
                                {
                                    int box = 4;
                                    int b = box;
                                    int x = 5 * b;
                                });
        }

        [Test]
        public void GetPropertyImplementation()
        {
            var props = new [] {"a","b","c","d"};
            var values = new object[] {1, DateTime.Now, 444m, "aaa",
                                       3, DateTime.Now, 4.55, false};

            string p = "a";
            object v=null;
            TestTime.Start(1e6, () => {
                                    if (p == "aasdads")
                                        v = values[4];
                                    else if (p == "b")
                                        v = values[4];
                                    else if (p == "c")
                                        v = values[4];
                                    else if (p == "d")
                                        v = values[4];
                                    else if (p == "e")
                                        v = values[4];
                                    else if (p == "f")
                                        v = values[4];
                                    else if (p == "g")
                                        v = values[4];
                                    else if (p == "h")
                                        v = values[4];
                                });

            var dic = new HybridDictionary();
            for (int i = 0; i < props.Length; i++)
                dic.Add(props[i], values[i]);

            TestTime.Start(1e6, () => { v = dic[p]; });
        }

        [Test]
        public void Collections()
        {
            int count = (int)1e4;
            int max = 1;
            int search = 677;

            Random r = new Random();

            TestTime.Start(count, () =>
                                  {
                                      var d = new List<Value>();

                                      for (int i = 0; i < max; i++)
                                      {
                                          var key = i.ToString();
                                          d.Add(new Value { Key = key });
                                      }
                                      for (int i = 0; i < search; i++)
                                      {
                                          var a = d.Find(v => v.Key == r.Next(max).ToString());
                                      }
                                  });
            Debug.WriteLine("----");
            TestTime.Start(count, () =>
                                  {
                                      var d = new HybridDictionary();

                                      for (int i = 0; i < max; i++)
                                      {
                                          var key = i.ToString();
                                          d.Add(key, new Value { Key = key });
                                      }
                                      for (int i = 0; i < search; i++)
                                      {
                                          var a = (Value)d[r.Next(max).ToString()];
                                      }
                                  });
            Debug.WriteLine("----");
            TestTime.Start(count, () =>
                                  {
                                      var d = new Dictionary<string, Value>();

                                      for (int i = 0; i < max; i++)
                                      {
                                          var key = i.ToString();
                                          d.Add(key, new Value { Key = key });
                                      }
                                      for (int i = 0; i < search; i++)
                                      {
                                          var a = d[r.Next(max).ToString()];
                                      }
                                  });
        }
    }
}